<template>
  <transition @after-enter="afterEnter" @after-leave="afterLeave" name="dialog-fade">
    <div :class="`${prefixCls}__wrapper`" @click.self="handleWrapperClick" v-show="visible">
      <div
        :class="[
          {
            'is-fullscreen': fullscreen,
            [prefixCls]: true,
            [`${prefixCls}--center`]: center
          },
          customClass
        ]"
        :key="key"
        :style="style"
        ref="dialog"
        role="dialog"
        v-loading="loading"
      >
        <div :class="`${prefixCls}__header`" @mousedown="onButtonDown">
          <slot name="title">
            <span :class="`${prefixCls}__title`">{{ title }}</span>
          </slot>
          <button
            :class="`${prefixCls}__headerbtn`"
            @click="handleClose"
            type="button"
            v-if="showClose"
          >
            <i :class="`${prefixCls}__close`" class="el-icon el-icon-close"></i>
          </button>
        </div>
        <div :class="`${prefixCls}__body`" v-if="rendered">
          <slot></slot>
        </div>
        <div :class="`${prefixCls}__footer`" v-if="$slots.footer">
          <slot name="footer"></slot>
        </div>
        <div :class="`${prefixCls}__footer`" v-else-if="onOk && onCancel">
          <el-button @click="onOk" type="primary" v-if="onOk" size="lg">{{okText || $t('saveText')}}</el-button>
          <el-button @click="onCancel" v-if="onCancel" size="lg">{{cancelText || $t('cancelText')}}</el-button>
        </div>
      </div>
    </div>
  </transition>
</template>

<script>
import Popup from 'element-ui/lib/utils/popup'
import { Emitter } from '@/mixins'
import { ConfigConsumerProps } from '@/components/config-provider'

export default {
  name: 'Modal',
  componentName: 'Modal',
  inject: {
    configProvider: { default: () => ConfigConsumerProps }
  },

  provide () {
    return {
      Modal: this
    }
  },

  mixins: [Popup, Emitter],

  props: {
    title: {
      type: String,
      default: ''
    },

    draggable: Boolean,

    modal: {
      type: Boolean,
      default: true
    },

    modalAppenmodelBody: {
      type: Boolean,
      default: true
    },

    appenmodelBody: {
      type: Boolean,
      default: false
    },

    lockScroll: {
      type: Boolean,
      default: true
    },

    closeOnClickModal: {
      type: Boolean,
      default: true
    },

    closeOnPressEscape: {
      type: Boolean,
      default: false
    },

    showClose: {
      type: Boolean,
      default: true
    },

    loading: Boolean,

    width: String,

    fullscreen: Boolean,

    customClass: {
      type: String,
      default: ''
    },
    top: {
      type: String,
      default: '15vh'
    },
    beforeClose: Function,
    center: {
      type: Boolean,
      default: false
    },

    destroyOnClose: {
      type: Boolean,
      default: true
    },
    onOk: Function,
    onCancel: Function,
    okText: String,
    cancelText: String
  },

  data () {
    return {
      closed: false,
      key: 0,
      timeId: null,
      leftPosition: 0,
      topPosition: 0
    }
  },

  watch: {
    visible (val) {
      if (val) {
        this.closed = false
        this.$emit('open')
        this.$el.addEventListener('scroll', this.updatePopper)
        this.$nextTick(() => {
          this.$refs.dialog.scrollTop = 0
        })
        if (this.appenmodelBody) {
          document.body.appendChild(this.$el)
        }
      } else {
        this.$el.removeEventListener('scroll', this.updatePopper)
        if (!this.closed) this.$emit('close')
        if (this.destroyOnClose) {
          this.$nextTick(() => {
            this.timeId = setTimeout(() => {
              // this.key++
              this.rendered = false
              clearTimeout(this.timeId)
              this.timeId = null
            }, 500)
          })
        }
      }
    }
  },

  computed: {
    prefixCls () {
      const getPrefixCls = this.configProvider.getPrefixCls
      return getPrefixCls('Modal')
    },
    style () {
      let style = {}
      if (!this.fullscreen) {
        style.marginTop = this.top
        if (this.width) {
          style.width = this.width
        }
      }
      if (this.draggable) {}
      return style
    }
  },

  methods: {
    onButtonDown (event) {
      if (!this.draggable) {
        return
      }

      this.onDragStart(event)
      window.addEventListener('mousemove', this.onDragging)
      window.addEventListener('mouseup', this.onDragEnd)

      event.preventDefault()
    },

    handleWrapperClick () {
      if (!this.closeOnClickModal) return
      this.handleClose()
    },
    handleClose () {
      if (typeof this.beforeClose === 'function') {
        this.beforeClose(this.hide)
      } else {
        this.hide()
      }
    },
    hide (cancel) {
      if (cancel !== false) {
        this.$emit('update:visible', false)
        this.$emit('close')
        this.closed = true
      }
    },
    updatePopper () {
      this.broadcast('ElSelectDropdown', 'updatePopper')
      this.broadcast('ElDropdownMenu', 'updatePopper')
    },
    afterEnter () {
      this.$emit('opened')
    },
    afterLeave () {
      this.$emit('closed')
    }
  },

  mounted () {
    if (this.visible) {
      this.rendered = true
      this.open()
      if (this.appenmodelBody) {
        document.body.appendChild(this.$el)
      }
    }
  },

  destroyed () {
    if (this.appenmodelBody && this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el)
    }
  }
}
</script>
